package com.atguigu.bigdata.scala.chapter11;
import java.util.*;
public class Scala02_Generic_Java {
    public static void main(String[] args) {
        // TODO 泛型
        // TODO 1. 泛型和类型的关系
        // 泛型和类型无关，不能当成整体来使用
        // 当泛型相同时，考虑类型的父子关系，如果泛型不相同，类型不会考虑父子关系
        List<String> list = new ArrayList<String>();
        test2(list);

        // TODO 2. 泛型的变化
        // 泛型是不可变的。不会考虑父子关系
        List<Student> studentList1 = new ArrayList<Student>();
//        List<Student> studentList2 = new ArrayList<Parent>();
//        List<Student> studentList3 = new ArrayList<Child>();

        // TODO 3. 泛型的上限和下限
        // 一般用于生产数据和消费数据

        // 生产数据时，保证数据持有最基本功能（转换）
        //设置了p这个对象调用produce方法时,Message内部数据类型的下限为Student,往上找,所以参数可以是new Message<Parent>
        Producer<Student> p = new Producer<Student>();
        p.produce(new Message<Student>());
        p.produce(new Message<Parent>());
//        p.produce(new Message<Child>());//错误

        //设置了p这个对象调用produceA方法时,Message内部数据类型的上限为Student,往下找,所以参数可以是new Message<Child>
        p.produceA(new Message<Student>());
        p.produceA(new Message<Child>());
 //       p.produceA(new Message<Parent>());//错误

        // 消费数据时，需要保证获取的数据功能不丢失，所以需要限定它的类型，这种称之为上限
        Consumer<Student> c = new Consumer<Student>();
        Message<? extends Student> message = c.consume();
        Student data = message.data;

    }
    public static void test1( List<Object> list ) {

    }
    public static void test2( Collection<String> list ) {

    }
}
class Parent {

}
class Student extends Parent{

}
class Child extends Student {

}
class Message<T> {
    public T data;
}
class Producer<T> {
    // 设置泛型的下限
    public void produce( Message<? super T> m ) {

    }
    // 设置泛型的上限
    public void produceA( Message<? extends T> m ) {

    }
}
class Consumer<T> {
    // 设置泛型的上限
    public Message<? extends T> consume() {
        return null;
    }
}